#coding=utf8
import sys
from core.ws_request import WebSocketRequest
from core.ws_response import Stop

from ws_setting import core_logger, CUSTOM_OBJ_SESSION_ID_NAME

class HandleMessageFilter:
    """
        to_user
            如果to_user为空， 则将数据发送给自己, 默认返回(self的session )
            如果类型为str: str应该为需要发送的session 
            如果类型为: str应该为需要发送的session 
            list, tuple, set: 如果item为str，则把它当做session id 返回
                              如果item为obj，并且声明了key属性名称(没有声明key，则使用默认key) , 使用obj.key作为session id返回(并需要保证其属性和值存在)
                                             
    """
    def before_process(self, session, *args, **kargs):
        try:
            session.request = WebSocketRequest(session)
            #if exist a special method to execute , using it instead of receiving data from socket
            _specified = kargs.get("method", None)
            if not _specified:
                session.data = session.recv_data()
                if not session.data:
                    core_logger.info("session was closed by browse")
                    session.closed = True
        except :
            session.closed = True
            core_logger.error("session cannot receive data ")




    def after_process(self, session, response, *args, **kargs):
        core_logger.debug("in after_process in message")
        while len(session.commands) > 0:
            cmd = session.commands.pop(0)
            to_sessions = self.get_send_sessions(session, cmd.pop("to"))
            if to_sessions:
                cmd["to_sessions"] = to_sessions
                cmd["current"] = session
                async = cmd.pop("async")
                if async:
                    session.app_container.message_sender_queue.put(cmd)
                else:
                    cmd.pop("handle")(**cmd)

        core_logger.debug("out after_process in message")

    def get_send_sessions(self, session, to):
        """
            获取需要发送的客户端
        """
        core_logger.debug("in get_send_sessions in message")
        to_sessions = list()

        if to is not None:
            if to:
                all_sessions = session.app_container.get_sessions()
                to_sessions = self.get_sessions(all_sessions, to)
        else:
            #send to myself
            to_sessions = (session,)
            core_logger.info("[ send message to = myself ]")
        return  to_sessions


    def get_sessions(self, all_session, custom_client):
        if not isinstance(all_session, dict):
            raise RuntimeError('all session 必须为dict或dict的子类')
        """
            get send to client sessions
        """
        session_ids = self.get_session_id_values(custom_client)
        core_logger.debug("need to send sessions %s and find out legal session" % session_ids)
        return [all_session[cid] for cid in session_ids if cid in all_session]

    def get_session_id_values(self, custom_client):
        """
            all custom obj that extends WsObject has  "CUSTOM_OBJ_SESSION_ID_NAME" attribute that is session id
            get session id from request.attr(CUSTOM_OBJ_SESSION_ID_NAME)
        """
        sids = []

        def add_ids(obj):
            # if object convert to dict
            if not isinstance(obj, dict) and hasattr(obj, "__dict__"):
                obj = obj.__dict__

            if isinstance(obj, dict) and CUSTOM_OBJ_SESSION_ID_NAME in obj:
                sids.append(obj[CUSTOM_OBJ_SESSION_ID_NAME])
            if isinstance(obj, str):
                sids.append(obj)
            if isinstance(obj, int):
                sids.append(str(obj))


        add_ids(custom_client)

        if not sids and hasattr(custom_client, "__iter__") and not isinstance(custom_client, dict):
            # only if iterable obj but dict
            for to_user_obj in custom_client:
                add_ids(to_user_obj)

        if sids:
            return sids
        else:
            raise RuntimeError("custom class need property %s " % CUSTOM_OBJ_SESSION_ID_NAME)
         

